package cn.ciis.sys.gencode.util;

import cn.ciis.basic.kit.CiisKit;
import cn.ciis.basic.model.GeneratorModel;
import com.jfinal.kit.Kv;
import com.jfinal.kit.LogKit;
import com.jfinal.kit.PathKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.activerecord.dialect.MysqlDialect;
import com.jfinal.plugin.activerecord.generator.DataDictionaryGenerator;
import com.jfinal.plugin.activerecord.generator.MetaBuilder;
import com.jfinal.plugin.activerecord.generator.TableMeta;

import javax.sql.DataSource;
import java.io.*;
import java.util.List;

/** 代码生成器 */
public class JfGenerator {

  public static final JfGenerator me = new JfGenerator();
  protected final JfEnjoy jfEngine = new JfEnjoy();

  protected Kv tablemetaMap = null;
  protected String packageBase = "cn.ciis";
  protected String srcFolder = "src";
  protected String viewFolder = "WebRoot";
  protected String basePath = "";

  public JfGenerator setPackageBase(String packageBase) {
    this.packageBase = packageBase;
    return this;
  }

  public JfGenerator setBasePath(String basePath) {
    this.basePath = basePath;
    return this;
  }

  public JfGenerator setSrcFolder(String srcFolder) {
    this.srcFolder = srcFolder;
    return this;
  }

  public JfGenerator setViewFolder(String viewFolder) {
    this.viewFolder = viewFolder;
    return this;
  }

  protected class DataGenerator extends DataDictionaryGenerator {
    public DataGenerator(DataSource dataSource, String dataDictionaryOutputDir) {
      super(dataSource, dataDictionaryOutputDir);
    }

    @Override
    public void rebuildColumnMetas(List<TableMeta> tableMetas) {
      super.rebuildColumnMetas(tableMetas);
    }
  };

  public TableMeta getTableMeta(String tableName) {
    if (tablemetaMap == null) {

      DataSource dataSource = GeneratorModel.getDataSource();

      MetaBuilder metaBuilder = new MetaBuilder(dataSource);
      metaBuilder.setDialect(new MysqlDialect());
      List<TableMeta> tableMetas = metaBuilder.build();
      new DataGenerator(dataSource, null).rebuildColumnMetas(tableMetas);

      if (tableMetas.size() == 0) {
        LogKit.info("TableMeta 数量为 0，不生成任何文件");
        return null;
      }
      Kv kv = Kv.create();
      for (TableMeta tableMeta : tableMetas) {
        kv.set(tableMeta.name, tableMeta);
      }
      tablemetaMap = kv;
    }
    return (TableMeta) tablemetaMap.get(tableName);
  }

  /** 生成手脚架代码 */
  public JfGenerator allRender(String className, String tableName, String tableNote,String sqlPage,String srcFolder) {
    return javaRender(className, tableName, tableNote,srcFolder).htmlRender(className, tableName,tableNote,srcFolder).sqlRender(tableName,tableNote,sqlPage).routesRender(className,tableNote,srcFolder);
  }

  /** java 代码生成 */
  public JfGenerator javaRender(String className,String tableName, String tableNote,String srcFolder) {
    // 刷新 映射对象
    // GeneratorModel.main(null);

    return controller(className,tableName, tableNote)
        .validator(className,tableName, tableNote)
        .service(className, tableName, tableNote);
  }

  private String toClassNameSmall(String className) {
    return new StringBuffer(className.substring(0, 1).toLowerCase())
        .append(className.substring(1))
        .toString();
  }

  private String toPackages(String className) {
    return new StringBuffer(packageBase)
        .append(".")
        .append(basePath)
        .append(className.toLowerCase())
        .toString();
  }

  /**
   * 生成Controller
   *
   * @param className 类名称
   */
  public JfGenerator controller(String className,String tableName, String tableNote) {
    String packages = toPackages(className);
    System.out.println("packages"+packages);
    String classNameSmall = toClassNameSmall(className);
    jfEngine.render(
        "/java/controller.jmis",
        Kv.by("package", "cn.ciis." + packages)
            .set("className", className)
            .set("classNameSmall", classNameSmall)
            .set("basePath", basePath)
            .set("tableName",tableName)
            .set("tableNote", tableNote),
        new StringBuilder()
            .append(System.getProperty("user.dir"))
            .append("/")
            .append(srcFolder)
            .append("/")
            .append(packages.replace(".", "/"))
            .append("/")
            .append(className)
            .append("AdminController.java"));
    return this;
  }

  /**
   * 生成validator
   *
   * @param className 类名称
   */
  public JfGenerator validator(String className,String tableName, String tableNote) {
    String packages = toPackages(className);

    String classNameSmall = toClassNameSmall(className);
    List<Record> records = tableInfoList(tableName);
    jfEngine.render(
        "/java/validator.jmis",
        Kv.by("package", "cn.ciis." + packages)
            .set("className", className)
            .set("classNameSmall", classNameSmall)
            .set("tableNote", tableNote)
            .set("tableList",records),
        new StringBuilder()
            .append(System.getProperty("user.dir"))
            .append("/")
            .append(srcFolder)
            .append("/")
            .append(packages.replace(".", "/"))
            .append("/")
            .append(className)
            .append("AdminValidator.java"));
    return this;
  }

  /**
   * 生成Service
   *
   * @param className 类名称
   * @param tableName 表名
   */
  public JfGenerator service(String className, String tableName, String tableNote) {
    String packages = toPackages(className);

    String classNameSmall = toClassNameSmall(className);

    jfEngine.render(
        "/java/service.jmis",
        Kv.by("package", "cn.ciis." + packages)
            .set("className", className)
            .set("classNameSmall", classNameSmall)
            .set("tableName", tableName)
            .set("tableNote", tableNote),
        new StringBuilder()
            .append(System.getProperty("user.dir"))
            .append("/")
            .append(srcFolder)
            .append("/")
            .append(packages.replace(".", "/"))
            .append("/")
            .append(className)
            .append("AdminService.java"));
    return this;
  }

  /**
   * 页面代码生成
   * @param className
   * @param tableName
   */
  public JfGenerator htmlRender(String className, String tableName,String tableNote,String srcFolder) {
    TableMeta tablemeta = getTableMeta(tableName);
    return htmlIndex(className, tablemeta,tableNote,tableName,srcFolder).htmlAddOrEdit(className,tablemeta,tableNote,tableName,srcFolder);
  }

  /**
   * 获取表字段及注释
   * @param tableName
   * @return
   */
  public List<Record> tableInfoList(String tableName){
    return Db.find("select column_name,column_comment from information_schema.columns where table_name=?",tableName);
  }

  public JfGenerator htmlIndex(String className, TableMeta tablemeta,String tableNote,String tableName,String srcFolder) {
    String packages = toPackages(className);
    String classNameSmall = toClassNameSmall(className);
    String basePathUrl = basePath.replace('.', '/');
    List<Record> records = tableInfoList(tableName);
    jfEngine.render(
        "/html/index.jmis",
        Kv.by("tablemeta", tablemeta)
            .set("package", packages)
            .set("className", className)
            .set("classNameSmall", classNameSmall)
            .set("basePath", basePathUrl)
            .set("tableNote",tableNote)
            .set("tableList",records)
            .set("classUrl",className.toLowerCase())
            .set("srcFolder",srcFolder),
        new StringBuilder()
            .append(PathKit.getWebRootPath())
            .append("/")
            .append("_view")
            .append("/")
            .append("_admin")
            .append("/")
            .append(viewFolder.substring(viewFolder.indexOf("_")))
            .append("/")
            .append(classNameSmall.toLowerCase())
            .append("/")
            .append("index.html"));
    return this;
  }
  public JfGenerator htmlAddOrEdit(String className, TableMeta tablemeta,String tableNote,String tableName,String srcFolder) {
    String packages = toPackages(className);
    String classNameSmall = toClassNameSmall(className);
    String basePathUrl = basePath.replace('.', '/');
    List<Record> records = tableInfoList(tableName);
    jfEngine.render(
            "/html/add_edit.jmis",
            Kv.by("tablemeta", tablemeta)
                    .set("package", packages)
                    .set("className", className)
                    .set("classNameSmall", classNameSmall)
                    .set("basePath", basePathUrl).set("tableNote",tableNote).set("tableList",records).set("srcFolder",srcFolder).set("classUrl",className.toLowerCase()),
            new StringBuilder()
                    .append(PathKit.getWebRootPath())
                    .append("/")
                    .append("_view")
                    .append("/")
                    .append("_admin")
                    .append("/")
                    .append(viewFolder.substring(viewFolder.indexOf("_")))
                    .append("/")
                    .append(classNameSmall.toLowerCase())
                    .append("/")
                    .append("add_edit.html"));
    return this;
  }

  public JfGenerator sqlRender(String tableName,String tableNote,String sqlPage) {
    return sqlModel(tableName,tableNote,sqlPage).sqlAll(tableName,tableNote);
  }

  public JfGenerator sqlModel(String tableName,String tableNote,String sqlPage) {
    List<Record> records = tableInfoList(tableName);
    try {
      jfEngine.render(
              "/sql/sql.jmis",
              Kv.by("tableName",tableName).set("tableNote",tableNote).set("tableList",records).set("sqlPage",sqlPage),
              new StringBuilder()
                      .append(new File("").getCanonicalPath())
                      .append("/").append("src").append("/").append("main").append("/").append("resources").append("/").append("sql").append("/")
                      .append(tableName+".sql"));
    } catch (IOException e) {
      e.printStackTrace();
    }
    return this;
  }

  public JfGenerator sqlAll(String tableName,String tableNote) {
    try {
      String allsqlPath=new File("").getCanonicalPath()+File.separator+"src"+File.separator+"main"+File.separator+"resources"+File.separator+"sql"+File.separator+"_all_sqls.sql";
      boolean stringInFile = CiisKit.findStringInFile(allsqlPath, tableName);
      if (!stringInFile){
        File fileOrFilename = new File(allsqlPath);
        BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileOrFilename, true)));
        out.write("\n");
        out.write("####"+tableNote+"\n");
        out.write("#namespace(\""+tableName+"\")");
        out.write("\r#include(\""+tableName+".sql\")\n");
        out.write("#end");
        out.close();
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
    return this;
  }


  public JfGenerator routesRender(String className,String tableNote,String srcFolder) {
    return routesFile(className,tableNote,srcFolder);
  }

  public JfGenerator routesFile(String className,String tableNote,String srcFolder){
    String classNameSmall = toClassNameSmall(className);
    String route = CiisKit.upperFirstLatter(srcFolder)+"Routes.java";
    try {
      String routeFile=new File("").getCanonicalPath()+"/src/main/java/cn/ciis/basic/routes/"+route;
      boolean stringInFile = CiisKit.findStringInFile(routeFile, className + "AdminController");
      if (!stringInFile){
        CiisKit.writeParagraph( routeFile,  "//匹配路由信息",  "		//"+tableNote+"\n		add(\"/admin/"+srcFolder+"/"+classNameSmall.toLowerCase()+"\", "+className+"AdminController.class, \"/"+className.toLowerCase()+"\");",  null);
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
    return this;
  }
}
